我一直用python2.x,python2.x内置的字符编码方式是unicode,这就对中文的处理造成了一些困扰,尤其是在用tornado写json接口的时候,如果不做处理,出来的没有中文,都是\x4d5f之类的东西。所以通常需要这样去处理下。
除了正常的
#!/usr/bin/env python
#coding: utf-8
之外
import sys reload(sys) sys.setdefaultencoding('utf-8')
是不可少的
另外,在做json.dumps的时候
self.write(response.body)
ensure_ascii=False需要有,才能正常的在json中显示中文。
这个是json包处理的问题而不是tornado处理的问题,self.write()中直接写中文则不会发生该问题。
关于tornado的httpclient异步回调功能,用一个简单的例子表达,访问baidu的IP地址查询库
class QueryIPHandler(tornado.web.RequestHandler): @tornado.web.asynchronous @tornado.gen.coroutine def get(self, *args, **kwargs): ip = self.get_argument('ip') local_ip = self.request.headers['X-Real-IP'] conf = Config.get_config() base_url = 'http://apis.baidu.com/apistore/iplookupservice/iplookup' params = {} params['ip'] = ip try: http = tornado.httpclient.AsyncHTTPClient() headers = dict(self.request.headers) headers['apikey'] = conf['BAIDU_APIKEY'] response = yield http.fetch( tornado.httpclient.HTTPRequest( url = base_url, headers=headers, method='POST', body=json.dumps(params, ensure_ascii=False) ) ) self.write(response.body) except tornado.httpclient.HTTPError, e: self.write(e)
使用web.asychronous修饰,使用gen.coroutine修饰,个人认为使用协程的好处是不用再写回调方法了。
base_url是需要访问百度api网址
params是请求参数,也就是query_string,
然后尝试使用tornado.httpclient.AsyncHTTPClient()
headers需要封装成字典类型并加入baidu的apikey。
response = yield http.fetch就是异步回调的"主体思想",用协程和yield方式就不需要像以前一样写回调函数了。
body参数按照tornado官方文档是字符串而非字典,所以要把params变量dumps成json串传过去。
http.fetch里的可配置参数项参考
http://www.tornadoweb.org/en/stable/httpclient.html
剩下的就是异常处理了。
为何要异步非阻塞?因为tornado是单进程的,如果不异步非阻塞的话,假如访问baidu很慢,则tornado进程会被卡住,访问tornado的其他页面也会卡在那里等待,直到百度访问完成,其他页面才会响应,所同理,node也是单进程的,天生就是异步非阻塞的。相比于node,我个人觉得tornado 的好处在于,想阻塞就阻塞,想非阻塞就非阻塞,很灵活,而node想写一个同步阻塞的应用就很麻烦了。
----20150815修订----
通过看源码得知,字符串处理可以使用tornado.escape,如tornado.escape.json_encode(dict),但是中文也会出现问题,tornado.escape内部对json_encode的处理也是对json包的二次封装,对于包含中文的内容,需要使用tornado.escape.json_encode(dict).decode('unicode_escape')处理就可以得到正确的结果。
不得不说,tornado的文档结构很好,就是说明台简单了,也缺少例子的支持,想深入了解,还是得自己看源码。